home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / migcom / sprite / RCS / server.c,OLD < prev   
Encoding:
Text File  |  1991-10-30  |  41.3 KB  |  1,527 lines

  1. head     1.2;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.2
  10. date     91.10.30.12.23.21;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.1;
  13.  
  14. 1.1
  15. date     91.10.29.22.23.48;  author kupfer;  state Exp;
  16. branches ;
  17. next     ;
  18.  
  19.  
  20. desc
  21. @@
  22.  
  23.  
  24. 1.2
  25. log
  26. @Add casts to a ?: expression to make the MIPS compiler happy.
  27. @
  28. text
  29. @/* 
  30.  * Mach Operating System
  31.  * Copyright (c) 1991,1990 Carnegie Mellon University
  32.  * All Rights Reserved.
  33.  * 
  34.  * Permission to use, copy, modify and distribute this software and its
  35.  * documentation is hereby granted, provided that both the copyright
  36.  * notice and this permission notice appear in all copies of the
  37.  * software, derivative works or modified versions, and any portions
  38.  * thereof, and that both notices appear in supporting documentation.
  39.  * 
  40.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  41.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  42.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  43.  * 
  44.  * Carnegie Mellon requests users of this software to return to
  45.  * 
  46.  *  Software Distribution Coordinator  or  Software.Distribution@@CS.CMU.EDU
  47.  *  School of Computer Science
  48.  *  Carnegie Mellon University
  49.  *  Pittsburgh PA 15213-3890
  50.  * 
  51.  * any improvements or extensions that they make and grant Carnegie Mellon
  52.  * the rights to redistribute these changes.
  53.  */
  54. /*
  55.  * HISTORY
  56.  * $Log:    server.c,v $
  57.  * Revision 1.1  91/10/29  22:23:48  kupfer
  58.  * Initial revision
  59.  * 
  60.  * Revision 2.6  91/08/28  11:17:21  jsb
  61.  *     Replaced ServerProcName with ServerDemux.
  62.  *     [91/08/13            rpd]
  63.  * 
  64.  *     Removed Camelot and TrapRoutine support.
  65.  *     Changed MsgKind to MsgSeqno.
  66.  *     [91/08/12            rpd]
  67.  * 
  68.  * Revision 2.5  91/07/31  18:10:51  dbg
  69.  *     Allow indefinite-length variable arrays.  They may be copied
  70.  *     either in-line or out-of-line, depending on size.
  71.  * 
  72.  *     Copy variable-length C Strings with mig_strncpy, to combine
  73.  *     'strcpy' and 'strlen' operations.
  74.  * 
  75.  *     New method for advancing request message pointer past
  76.  *     variable-length arguments.  We no longer have to know the order
  77.  *     of variable-length arguments and their count arguments.
  78.  * 
  79.  *     Remove redundant assignments (to msgh_simple, msgh_size) in
  80.  *     generated code.
  81.  *     [91/07/17            dbg]
  82.  * 
  83.  * Revision 2.4  91/06/25  10:31:51  rpd
  84.  *     Cast request and reply ports to ipc_port_t in KernelServer stubs.
  85.  *     [91/05/27            rpd]
  86.  * 
  87.  * Revision 2.3  91/02/05  17:55:37  mrt
  88.  *     Changed to new Mach copyright
  89.  *     [91/02/01  17:55:30  mrt]
  90.  * 
  91.  * Revision 2.2  90/06/02  15:05:29  rpd
  92.  *     Created for new IPC.
  93.  *     [90/03/26  21:13:12  rpd]
  94.  * 
  95.  * 07-Apr-89  Richard Draves (rpd) at Carnegie-Mellon University
  96.  *    Extensive revamping.  Added polymorphic arguments.
  97.  *    Allow multiple variable-sized inline arguments in messages.
  98.  *
  99.  * 18-Oct-88  Mary Thompson (mrt) at Carnegie-Mellon University
  100.  *    Set the local port in the server reply message to
  101.  *    MACH_PORT_NULL for greater efficiency and to make Camelot
  102.  *    happy.
  103.  *
  104.  * 18-Apr-88  Mary Thompson (mrt) at Carnegie-Mellon University
  105.  *    Changed call to WriteLocalVarDecl in WriteMsgVarDecl
  106.  *    to write out the parameters for the C++ code to a call
  107.  *    a new routine WriteServerVarDecl which includes the *
  108.  *    for reference variable, but uses the transType if it
  109.  *    exists.
  110.  *
  111.  * 27-Feb-88  Richard Draves (rpd) at Carnegie-Mellon University
  112.  *    Changed reply message initialization for camelot interfaces.
  113.  *    Now we assume camelot interfaces are all camelotroutines and
  114.  *    always initialize the dummy field & tid field.  This fixes
  115.  *    the wrapper-server-call bug in distributed transactions.
  116.  *
  117.  * 23-Feb-88  Mary Thompson (mrt) at Carnegie-Mellon University
  118.  *    Changed the include of camelot_types.h to cam/camelot_types.h
  119.  *
  120.  * 19-Feb-88  Mary Thompson (mrt) at Carnegie-Mellon University
  121.  *    Fixed WriteDestroyArg to not call the destructor
  122.  *    function on any in/out args.
  123.  *
  124.  *  4-Feb-88  Mary Thompson (mrt) at Carnegie-Mellon University
  125.  *    Fixed dld's code to write out parameter list to
  126.  *    use WriteLocalVarDecl to get transType or ServType if
  127.  *    they exist.
  128.  *
  129.  * 19-Jan-88  David Golub (dbg) at Carnegie-Mellon University
  130.  *    Change variable-length inline array declarations to use
  131.  *    maximum size specified to Mig.  Make message variable
  132.  *    length if the last item in the message is variable-length
  133.  *    and inline.  Use argMultipler field to convert between
  134.  *    argument and IPC element counts.
  135.  *
  136.  * 18-Jan-88  David Detlefs (dld) at Carnegie-Mellon University
  137.  *    Modified to produce C++ compatible code via #ifdefs.
  138.  *    All changes have to do with argument declarations.
  139.  *
  140.  *  2-Dec-87  David Golub (dbg) at Carnegie-Mellon University
  141.  *    Added destructor function for IN arguments to server.
  142.  *
  143.  * 18-Nov-87  Jeffrey Eppinger (jle) at Carnegie-Mellon University
  144.  *    Changed to typedef "novalue" as "void" if we're using hc.
  145.  *
  146.  * 17-Sep-87  Bennet Yee (bsy) at Carnegie-Mellon University
  147.  *    Added _<system>SymTab{Base|End} for use with security
  148.  *    dispatch routine.  It is neccessary for the authorization
  149.  *    system to know the operations by symbolic names.
  150.  *    It is harmless to user code as it only means an extra
  151.  *    array if it is accidentally turned on.
  152.  *
  153.  * 24-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
  154.  *    Corrected the setting of retcode for CamelotRoutines.
  155.  *
  156.  * 21-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
  157.  *    Added deallocflag to call to WritePackArgType.
  158.  *
  159.  * 14-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
  160.  *    Moved type declarations and assignments for DummyType 
  161.  *    and tidType to server demux routine. Automatically
  162.  *    include camelot_types.h and msg_types.h for interfaces 
  163.  *    containing camelotRoutines.
  164.  *
  165.  *  8-Jun-87  Mary Thompson (mrt) at Carnegie-Mellon University
  166.  *    Removed #include of sys/types.h and strings.h from WriteIncludes.
  167.  *    Changed the KERNEL include from ../h to sys/
  168.  *    Removed extern from WriteServer to make hi-c happy
  169.  *
  170.  * 28-May-87  Richard Draves (rpd) at Carnegie-Mellon University
  171.  *    Created.
  172.  */
  173.  
  174. #include <assert.h>
  175.  
  176. #include <mach/message.h>
  177. #include "write.h"
  178. #include "utils.h"
  179. #include "global.h"
  180.  
  181. static void
  182. WriteIncludes(file)
  183.     FILE *file;
  184. {
  185.     fprintf(file, "#define EXPORT_BOOLEAN\n");
  186.     fprintf(file, "#include <mach/boolean.h>\n");
  187.     fprintf(file, "#include <mach/kern_return.h>\n");
  188.     fprintf(file, "#include <mach/message.h>\n");
  189.     fprintf(file, "#include <mach/mig_errors.h>\n");
  190.     if (IsKernelServer)
  191.     fprintf(file, "#include <ipc/ipc_port.h>\n");
  192.     fprintf(file, "\n");
  193. }
  194.  
  195. static void
  196. WriteGlobalDecls(file)
  197.     FILE *file;
  198. {
  199.     fprintf(file, "/* Due to pcc compiler bug, cannot use void */\n");
  200.     fprintf(file, "#if\t%s || defined(hc)\n", NewCDecl);
  201.     fprintf(file, "#define novalue void\n");
  202.     fprintf(file, "#else\n");
  203.     fprintf(file, "#define novalue int\n");
  204.     fprintf(file, "#endif\n");
  205.     fprintf(file, "\n");
  206.  
  207.     if (RCSId != strNULL)
  208.     WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId);
  209.  
  210.     /* Used for locations in the request message, *not* reply message.
  211.        Reply message locations aren't dependent on IsKernelServer. */
  212.  
  213.     if (IsKernelServer)
  214.     {
  215.     fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
  216.     fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
  217.     fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
  218.     fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
  219.     fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
  220.     fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
  221.     }
  222.     else
  223.     {
  224.     fprintf(file, "#define msgh_request_port\tmsgh_local_port\n");
  225.     fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
  226.     fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
  227.     fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n");
  228.     fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
  229.     fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
  230.     }
  231.     fprintf(file, "\n");
  232. }
  233.  
  234. static void
  235. WriteProlog(file)
  236.     FILE *file;
  237. {
  238.     fprintf(file, "/* Module %s */\n", SubsystemName);
  239.     fprintf(file, "\n");
  240.     
  241.     WriteIncludes(file);
  242.     WriteBogusDefines(file);
  243.     WriteGlobalDecls(file);
  244. }
  245.  
  246.  
  247. static void
  248. WriteSymTabEntries(file, stats)
  249.     FILE *file;
  250.     statement_t *stats;
  251. {
  252.     register statement_t *stat;
  253.     register u_int current = 0;
  254.  
  255.     for (stat = stats; stat != stNULL; stat = stat->stNext)
  256.     if (stat->stKind == skRoutine) {
  257.         register    num = stat->stRoutine->rtNumber;
  258.         char    *name = stat->stRoutine->rtName;
  259.         while (++current <= num)
  260.         fprintf(file,"\t\t\t{ \"\", 0, 0 },\n");
  261.         fprintf(file, "\t{ \"%s\", %d, _X%s },\n",
  262.             name,
  263.         SubsystemBase + current - 1,
  264.         name);
  265.     }
  266.     while (++current <= rtNumber)
  267.     fprintf(file,"\t{ \"\", 0, 0 },\n");
  268. }
  269.  
  270. static void
  271. WriteArrayEntries(file, stats)
  272.     FILE *file;
  273.     statement_t *stats;
  274. {
  275.     register u_int current = 0;
  276.     register statement_t *stat;
  277.  
  278.     for (stat = stats; stat != stNULL; stat = stat->stNext)
  279.     if (stat->stKind == skRoutine)
  280.     {
  281.         register routine_t *rt = stat->stRoutine;
  282.  
  283.         while (current++ < rt->rtNumber)
  284.         fprintf(file, "\t\t0,\n");
  285.         fprintf(file, "\t\t_X%s,\n", rt->rtName);
  286.     }
  287.     while (current++ < rtNumber)
  288.     fprintf(file, "\t\t\t0,\n");
  289. }
  290.  
  291. static void
  292. WriteEpilog(file, stats)
  293.     FILE *file;
  294.     statement_t *stats;
  295. {
  296.     fprintf(file, "\n");
  297.  
  298.     fprintf(file, "mig_external boolean_t %s\n", ServerDemux);
  299.     fprintf(file, "#if\t%s\n", NewCDecl);
  300.     fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
  301.     fprintf(file, "#else\n");
  302.     fprintf(file, "\t(InHeadP, OutHeadP)\n");
  303.     fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
  304.     fprintf(file, "#endif\n");
  305.  
  306.     fprintf(file, "{\n");
  307.     fprintf(file, "\tregister mach_msg_header_t *InP =  InHeadP;\n");
  308.  
  309.     fprintf(file, "\tregister mig_reply_header_t *OutP = (mig_reply_header_t *) OutHeadP;\n");
  310.  
  311.     fprintf(file, "\n");
  312.  
  313.     WriteStaticDecl(file, itRetCodeType,
  314.             itRetCodeType->itDeallocate, itRetCodeType->itLongForm,
  315.             !IsKernelServer, "RetCodeType");
  316.     fprintf(file, "\n");
  317.  
  318.     fprintf(file, "\ttypedef novalue (*SERVER_STUB_PROC)\n");
  319.     fprintf(file, "#if\t%s\n", NewCDecl);
  320.     fprintf(file, "\t\t(mach_msg_header_t *, mach_msg_header_t *);\n");
  321.     fprintf(file, "#else\n");
  322.     fprintf(file, "\t\t();\n");
  323.     fprintf(file, "#endif\n");
  324.     fprintf(file, "\tstatic SERVER_STUB_PROC routines[] = {\n");
  325.  
  326.     WriteArrayEntries(file, stats);
  327.  
  328.     fprintf(file, "\t};\n");
  329.     fprintf(file, "\n");
  330.     fprintf(file, "\tregister SERVER_STUB_PROC routine;\n");
  331.     fprintf(file, "\n");
  332.  
  333.     fprintf(file, "\tOutP->Head.msgh_bits = ");
  334.     fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InP->msgh_bits), 0);\n");
  335.     fprintf(file, "\tOutP->Head.msgh_size = sizeof *OutP;\n");
  336.     fprintf(file, "\tOutP->Head.msgh_remote_port = InP->msgh_reply_port;\n");
  337.     fprintf(file, "\tOutP->Head.msgh_local_port = MACH_PORT_NULL;\n");
  338.     fprintf(file, "\tOutP->Head.msgh_seqno = 0;\n");
  339.     fprintf(file, "\tOutP->Head.msgh_id = InP->msgh_id + 100;\n");
  340.     fprintf(file, "\n");
  341.     WritePackMsgType(file, itRetCodeType,
  342.              itRetCodeType->itDeallocate, itRetCodeType->itLongForm,
  343.              !IsKernelServer, "OutP->RetCodeType", "RetCodeType");
  344.     fprintf(file, "\n");
  345.  
  346.     fprintf(file, "\tif ((InP->msgh_id > %d) || (InP->msgh_id < %d) ||\n",
  347.         SubsystemBase + rtNumber - 1, SubsystemBase);
  348.     fprintf(file, "\t    ((routine = routines[InP->msgh_id - %d]) == 0)) {\n",
  349.         SubsystemBase);
  350.     fprintf(file, "\t\tOutP->RetCode = MIG_BAD_ID;\n");
  351.     fprintf(file, "\t\treturn FALSE;\n");
  352.     fprintf(file, "\t}\n");
  353.  
  354.     /* Call appropriate routine */
  355.     fprintf(file, "\t(*routine) (InP, &OutP->Head);\n");
  356.     fprintf(file, "\treturn TRUE;\n");
  357.     fprintf(file, "}\n");
  358.  
  359.     /* symtab */
  360.  
  361.     if (GenSymTab) {
  362.     fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName);
  363.     WriteSymTabEntries(file,stats);
  364.     fprintf(file,"};\n");
  365.     fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase);
  366.     fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber);
  367.     }
  368. }
  369.  
  370. /*
  371.  *  Returns the return type of the server-side work function.
  372.  *  Suitable for "extern %s serverfunc()".
  373.  */
  374. static char *
  375. ServerSideType(rt)
  376.     routine_t *rt;
  377. {
  378.     if (rt->rtServerReturn == argNULL)
  379.     return "void";
  380.     else
  381.     return rt->rtServerReturn->argType->itTransType;
  382. }
  383.  
  384. static void
  385. WriteLocalVarDecl(file, arg)
  386.     FILE *file;
  387.     register argument_t *arg;
  388. {
  389.     register ipc_type_t *it = arg->argType;
  390.  
  391.     if (it->itInLine && it->itVarArray)
  392.     {
  393.     register ipc_type_t *btype = it->itElement;
  394.  
  395.     fprintf(file, "\t%s %s[%d]", btype->itTransType,
  396.         arg->argVarName, it->itNumber/btype->itNumber);
  397.     }
  398.     else
  399.     fprintf(file, "\t%s %s", it->itTransType, arg->argVarName);
  400. }
  401.  
  402. static void
  403. WriteServerArgDecl(file, arg)
  404.     FILE *file;
  405.     argument_t *arg;
  406. {
  407.     fprintf(file, "%s %s%s",
  408.         arg->argType->itTransType,
  409.         argByReferenceServer(arg) ? "*" : "",
  410.         arg->argVarName);
  411. }
  412.  
  413. /*
  414.  *  Writes the local variable declarations which are always
  415.  *  present:  InP, OutP, the server-side work function.
  416.  */
  417. static void
  418. WriteVarDecls(file, rt)
  419.     FILE *file;
  420.     routine_t *rt;
  421. {
  422.     int i;
  423.     boolean_t NeedMsghSize = FALSE;
  424.     boolean_t NeedMsghSizeDelta = FALSE;
  425.  
  426.     fprintf(file, "\tregister Request *In0P = (Request *) InHeadP;\n");
  427.     for (i = 1; i <= rt->rtMaxRequestPos; i++)
  428.     fprintf(file, "\tregister Request *In%dP;\n", i);
  429.     fprintf(file, "\tregister Reply *OutP = (Reply *) OutHeadP;\n");
  430.  
  431.     fprintf(file, "\tmig_external %s %s\n",
  432.         ServerSideType(rt), rt->rtServerName);
  433.     fprintf(file, "#if\t%s\n", NewCDecl);
  434.     fprintf(file, "\t\t(");
  435.     WriteList(file, rt->rtArgs, WriteServerArgDecl, akbServerArg, ", ", "");
  436.     fprintf(file, ");\n");
  437.     fprintf(file, "#else\n");
  438.     fprintf(file, "\t\t();\n");
  439.     fprintf(file, "#endif\n");
  440.     fprintf(file, "\n");
  441.  
  442.     if (!rt->rtSimpleFixedReply)
  443.     fprintf(file, "\tboolean_t msgh_simple;\n");
  444.     else if (!rt->rtSimpleCheckRequest)
  445.     {
  446.     fprintf(file, "#if\tTypeCheck\n");
  447.     fprintf(file, "\tboolean_t msgh_simple;\n");
  448.     fprintf(file, "#endif\tTypeCheck\n");
  449.     fprintf(file, "\n");
  450.     }
  451.  
  452.     /* if either request or reply is variable, we may need
  453.        msgh_size_delta and msgh_size */
  454.  
  455.     if (rt->rtNumRequestVar > 0)
  456.     NeedMsghSize = TRUE;
  457.     if (rt->rtMaxRequestPos > 0)
  458.     NeedMsghSizeDelta = TRUE;
  459.  
  460.     if (rt->rtNumReplyVar > 1)
  461.     NeedMsghSize = TRUE;
  462.     if (rt->rtMaxReplyPos > 0)
  463.     NeedMsghSizeDelta = TRUE;
  464.  
  465.     if (NeedMsghSize)
  466.     fprintf(file, "\tunsigned int msgh_size;\n");
  467.     if (NeedMsghSizeDelta)
  468.     fprintf(file, "\tunsigned int msgh_size_delta;\n");
  469.  
  470.     if (NeedMsghSize || NeedMsghSizeDelta)
  471.     fprintf(file, "\n");
  472. }
  473.  
  474. static void
  475. WriteMsgError(file, error)
  476.     FILE *file;
  477.     char *error;
  478. {
  479.     fprintf(file, "\t\t{ OutP->RetCode = %s; return; }\n", error);
  480. }
  481.  
  482. static void
  483. WriteReplyInit(file, rt)
  484.     FILE *file;
  485.     routine_t *rt;
  486. {
  487.     boolean_t printed_nl = FALSE;
  488.  
  489.     if (rt->rtSimpleFixedReply)
  490.     {
  491.     if (!rt->rtSimpleSendReply) /* complex reply message */
  492.     {
  493.         printed_nl = TRUE;
  494.         fprintf(file, "\n");
  495.         fprintf(file,
  496.         "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
  497.     }
  498.     }
  499.     else
  500.     {
  501.     printed_nl = TRUE;
  502.     fprintf(file, "\n");
  503.     fprintf(file, "\tmsgh_simple = %s;\n", 
  504.               strbool(rt->rtSimpleSendReply));
  505.     }
  506.  
  507.     if (rt->rtNumReplyVar == 0)
  508.     {
  509.     if (!printed_nl)
  510.         fprintf(file, "\n");
  511.     fprintf(file, "\tOutP->Head.msgh_size = %d;\n", rt->rtReplySize);
  512.     }
  513. }
  514.  
  515. static void
  516. WriteReplyHead(file, rt)
  517.     FILE *file;
  518.     routine_t *rt;
  519. {
  520.     if ((!rt->rtSimpleFixedReply) ||
  521.     (rt->rtNumReplyVar > 1))
  522.     {
  523.     fprintf(file, "\n");
  524.     if (rt->rtMaxReplyPos > 0)
  525.         fprintf(file, "\tOutP = (Reply *) OutHeadP;\n");
  526.     }
  527.  
  528.     if (!rt->rtSimpleFixedReply)
  529.     {
  530.     fprintf(file, "\tif (!msgh_simple)\n");
  531.     fprintf(file,
  532.         "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
  533.     }
  534.     if (rt->rtNumReplyVar > 1)
  535.     fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n");
  536. }
  537.  
  538. static void
  539. WriteCheckHead(file, rt)
  540.     FILE *file;
  541.     routine_t *rt;
  542. {
  543.     fprintf(file, "#if\tTypeCheck\n");
  544.     if (rt->rtNumRequestVar > 0)
  545.     fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n");
  546.     if (!rt->rtSimpleCheckRequest)
  547.     fprintf(file, "\tmsgh_simple = !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
  548.  
  549.     if (rt->rtNumRequestVar > 0)
  550.     fprintf(file, "\tif ((msgh_size < %d)",
  551.         rt->rtRequestSize);
  552.     else
  553.     fprintf(file, "\tif ((In0P->Head.msgh_size != %d)",
  554.         rt->rtRequestSize);
  555.  
  556.     if (rt->rtSimpleCheckRequest)
  557.     fprintf(file, " ||\n\t    %s(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)",
  558.         rt->rtSimpleReceiveRequest ? "" : "!");
  559.     fprintf(file, ")\n");
  560.     WriteMsgError(file, "MIG_BAD_ARGUMENTS");
  561.     fprintf(file, "#endif\tTypeCheck\n");
  562.     fprintf(file, "\n");
  563. }
  564.  
  565. static void
  566. WriteTypeCheck(file, arg)
  567.     FILE *file;
  568.     register argument_t *arg;
  569. {
  570.     register ipc_type_t *it = arg->argType;
  571.     register routine_t *rt = arg->argRoutine;
  572.  
  573.     fprintf(file, "#if\tTypeCheck\n");
  574.     if (akCheck(arg->argKind, akbRequestQC))
  575.     {
  576.     fprintf(file, "#if\tUseStaticMsgType\n");
  577.     fprintf(file, "\tif (* (int *) &In%dP->%s != * (int *) &%sCheck)\n",
  578.         arg->argRequestPos, arg->argTTName, arg->argVarName);
  579.     fprintf(file, "#else\tUseStaticMsgType\n");
  580.     }
  581.     fprintf(file, "\tif (");
  582.     if (!it->itIndefinite) {
  583.     fprintf(file, "(In%dP->%s%s.msgt_inline != %s) ||\n\t    ",
  584.         arg->argRequestPos, arg->argTTName,
  585.         arg->argLongForm ? ".msgtl_header" : "",
  586.         strbool(it->itInLine));
  587.     }
  588.     fprintf(file, "(In%dP->%s%s.msgt_longform != %s) ||\n",
  589.         arg->argRequestPos, arg->argTTName,
  590.         arg->argLongForm ? ".msgtl_header" : "",
  591.         strbool(arg->argLongForm));
  592.     if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
  593.     {
  594.     if (!rt->rtSimpleCheckRequest)
  595.         fprintf(file, "\t    (MACH_MSG_TYPE_PORT_ANY(In%dP->%s.msgt%s_name) && msgh_simple) ||\n",
  596.             arg->argRequestPos, arg->argTTName,
  597.             arg->argLongForm ? "l" : "");
  598.     }
  599.     else
  600.     fprintf(file, "\t    (In%dP->%s.msgt%s_name != %s) ||\n",
  601.         arg->argRequestPos, arg->argTTName,
  602.         arg->argLongForm ? "l" : "",
  603.         it->itOutNameStr);
  604.     if (!it->itVarArray)
  605.     fprintf(file, "\t    (In%dP->%s.msgt%s_number != %d) ||\n",
  606.         arg->argRequestPos, arg->argTTName,
  607.         arg->argLongForm ? "l" : "",
  608.         it->itNumber);
  609.     fprintf(file, "\t    (In%dP->%s.msgt%s_size != %d))\n",
  610.         arg->argRequestPos, arg->argTTName,
  611.         arg->argLongForm ? "l" : "",
  612.         it->itSize);
  613.     if (akCheck(arg->argKind, akbRequestQC))
  614.     fprintf(file, "#endif\tUseStaticMsgType\n");
  615.     WriteMsgError(file, "MIG_BAD_ARGUMENTS");
  616.     fprintf(file, "#endif\tTypeCheck\n");
  617.     fprintf(file, "\n");
  618. }
  619.  
  620. static void
  621. WriteCheckArgSize(file, arg)
  622.     FILE *file;
  623.     register argument_t *arg;
  624. {
  625.     register ipc_type_t *ptype = arg->argType;
  626.     register ipc_type_t *btype = ptype->itElement;
  627.     argument_t *count = arg->argCount;
  628.     int multiplier = btype->itTypeSize / btype->itNumber;
  629.  
  630.     if (ptype->itIndefinite) {
  631.     /*
  632.      * Check descriptor.  If out-of-line, use standard size.
  633.      */
  634.     fprintf(file, "(In%dP->%s.msgtl_header.msgt_inline) ? ",
  635.         arg->argRequestPos,
  636.         arg->argTTName);
  637.     }
  638.  
  639.     if (multiplier > 1)
  640.     fprintf(file, "%d * ", multiplier);
  641.  
  642.     fprintf(file, "In%dP->%s", arg->argRequestPos, count->argMsgField);
  643.  
  644.     /* If the base type size of the data field isn`t a multiple of 4,
  645.        we have to round up. */
  646.     if (btype->itTypeSize % 4 != 0)
  647.     fprintf(file, " + 3 & ~3");
  648.  
  649.     if (ptype->itIndefinite) {
  650.     fprintf(file, " : sizeof(%s *)", FetchServerType(btype));
  651.     }
  652. }
  653.  
  654. static void
  655. WriteCheckMsgSize(file, arg)
  656.     FILE *file;
  657.     register argument_t *arg;
  658. {
  659.     register routine_t *rt = arg->argRoutine;
  660.  
  661.     /* If there aren't any more In args after this, then
  662.        we can use the msgh_size_delta value directly in
  663.        the TypeCheck conditional. */
  664.  
  665.     if (arg->argRequestPos == rt->rtMaxRequestPos)
  666.     {
  667.     fprintf(file, "#if\tTypeCheck\n");
  668.     fprintf(file, "\tif (msgh_size != %d + (",
  669.         rt->rtRequestSize);
  670.     WriteCheckArgSize(file, arg);
  671.     fprintf(file, "))\n");
  672.  
  673.     WriteMsgError(file, "MIG_BAD_ARGUMENTS");
  674.     fprintf(file, "#endif\tTypeCheck\n");
  675.     }
  676.     else
  677.     {
  678.     /* If there aren't any more variable-sized arguments after this,
  679.        then we must check for exact msg-size and we don't need to
  680.        update msgh_size. */
  681.  
  682.     boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar;
  683.  
  684.     /* calculate the actual size in bytes of the data field.  note
  685.        that this quantity must be a multiple of four.  hence, if
  686.        the base type size isn't a multiple of four, we have to
  687.        round up.  note also that btype->itNumber must
  688.        divide btype->itTypeSize (see itCalculateSizeInfo). */
  689.  
  690.     fprintf(file, "\tmsgh_size_delta = ");
  691.     WriteCheckArgSize(file, arg);
  692.     fprintf(file, ";\n");
  693.     fprintf(file, "#if\tTypeCheck\n");
  694.  
  695.     /* Don't decrement msgh_size until we've checked that
  696.        it won't underflow. */
  697.  
  698.     if (LastVarArg)
  699.         fprintf(file, "\tif (msgh_size != %d + msgh_size_delta)\n",
  700.         rt->rtRequestSize);
  701.     else
  702.         fprintf(file, "\tif (msgh_size < %d + msgh_size_delta)\n",
  703.         rt->rtRequestSize);
  704.     WriteMsgError(file, "MIG_BAD_ARGUMENTS");
  705.  
  706.     if (!LastVarArg)
  707.         fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
  708.  
  709.     fprintf(file, "#endif\tTypeCheck\n");
  710.     }
  711.     fprintf(file, "\n");
  712. }
  713.  
  714. static char *
  715. InArgMsgField(arg)
  716.     register argument_t *arg;
  717. {
  718.     static char buffer[100];
  719.  
  720.     /*
  721.      *    Inside the kernel, the request and reply port fields
  722.      *    really hold ipc_port_t values, not mach_port_t values.
  723.      *    Hence we must cast the values.
  724.      */
  725.  
  726.     if (IsKernelServer &&
  727.     ((akIdent(arg->argKind) == akeRequestPort) ||
  728.      (akIdent(arg->argKind) == akeReplyPort)))
  729.     sprintf(buffer, "(ipc_port_t) In%dP->%s",
  730.         arg->argRequestPos, arg->argMsgField);
  731.     else
  732.     sprintf(buffer, "In%dP->%s",
  733.         arg->argRequestPos, arg->argMsgField);
  734.  
  735.     return buffer;
  736. }
  737.  
  738. static void
  739. WriteExtractArgValue(file, arg)
  740.     FILE *file;
  741.     register argument_t *arg;
  742. {
  743.     register ipc_type_t *it = arg->argType;
  744.  
  745.     if (arg->argMultiplier > 1)
  746.     WriteCopyType(file, it, "%s", "/* %s */ %s / %d",
  747.               arg->argVarName, InArgMsgField(arg), arg->argMultiplier);
  748.     else if (it->itInTrans != strNULL)
  749.     WriteCopyType(file, it, "%s", "/* %s */ %s(%s)",
  750.               arg->argVarName, it->itInTrans, InArgMsgField(arg));
  751.     else
  752.     WriteCopyType(file, it, "%s", "/* %s */ %s",
  753.               arg->argVarName, InArgMsgField(arg));
  754.     fprintf(file, "\n");
  755. }
  756.  
  757. static void
  758. WriteInitializeCount(file, arg)
  759.     FILE *file;
  760.     register argument_t *arg;
  761. {
  762.     register ipc_type_t *ptype = arg->argParent->argType;
  763.     register ipc_type_t *btype = ptype->itElement;
  764.  
  765.     /*
  766.      *    Initialize 'count' argument for variable-length inline OUT parameter
  767.      *    with maximum allowed number of elements.
  768.      */
  769.  
  770.     fprintf(file, "\t%s = %d;\n", arg->argVarName,
  771.         ptype->itNumber/btype->itNumber);
  772.     fprintf(file, "\n");
  773. }
  774.  
  775. static void
  776. WriteTypeCheckArg(file, arg)
  777.     FILE *file;
  778.     register argument_t *arg;
  779. {
  780.     if (akCheck(arg->argKind, akbRequest)) {
  781.     WriteTypeCheck(file, arg);
  782.  
  783.     if (akCheck(arg->argKind, akbVariable))
  784.         WriteCheckMsgSize(file, arg);
  785.     }
  786. }
  787.  
  788. WriteAdjustRequestMsgPtr(file, arg)
  789.     FILE *file;
  790.     register argument_t *arg;
  791. {
  792.     register ipc_type_t *ptype = arg->argType;
  793.  
  794.     fprintf(file,
  795.     "\tIn%dP = (Request *) ((char *) In%dP + msgh_size_delta - %d);\n\n",
  796.     arg->argRequestPos+1, arg->argRequestPos,
  797.     ptype->itTypeSize + ptype->itPadSize);
  798. }
  799.  
  800. WriteTypeCheckRequestArgs(file, rt)
  801.     FILE *file;
  802.     register routine_t *rt;
  803. {
  804.     register argument_t *arg;
  805.     register argument_t *lastVarArg;
  806.  
  807.     lastVarArg = argNULL;
  808.     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
  809.  
  810.     /*
  811.      * Advance message pointer if the last request argument was
  812.      * variable-length and the request position will change.
  813.      */
  814.     if (lastVarArg != argNULL &&
  815.         lastVarArg->argRequestPos < arg->argRequestPos)
  816.     {
  817.         WriteAdjustRequestMsgPtr(file, lastVarArg);
  818.         lastVarArg = argNULL;
  819.     }
  820.  
  821.     /*
  822.      * Type-check the argument.
  823.      */
  824.     WriteTypeCheckArg(file, arg);
  825.  
  826.     /*
  827.      * Remember whether this was variable-length.
  828.      */
  829.     if (akCheckAll(arg->argKind, akbVariable|akbRequest))
  830.         lastVarArg = arg;
  831.     }
  832. }
  833.  
  834. static void
  835. WriteExtractArg(file, arg)
  836.     FILE *file;
  837.     register argument_t *arg;
  838. {
  839.     if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded))
  840.     WriteExtractArgValue(file, arg);
  841.  
  842.     if ((akIdent(arg->argKind) == akeCount) &&
  843.     akCheck(arg->argKind, akbReturnSnd))
  844.     {
  845.     register ipc_type_t *ptype = arg->argParent->argType;
  846.  
  847.     if (ptype->itInLine && ptype->itVarArray)
  848.         WriteInitializeCount(file, arg);
  849.     }
  850. }
  851.  
  852. static void
  853. WriteServerCallArg(file, arg)
  854.     FILE *file;
  855.     register argument_t *arg;
  856. {
  857.     ipc_type_t *it = arg->argType;
  858.     boolean_t NeedClose = FALSE;
  859.  
  860.     if (argByReferenceServer(arg))
  861.     fprintf(file, "&");
  862.  
  863.     if ((it->itInTrans != strNULL) &&
  864.     akCheck(arg->argKind, akbSendRcv) &&
  865.     !akCheck(arg->argKind, akbVarNeeded))
  866.     {
  867.     fprintf(file, "%s(", it->itInTrans);
  868.     NeedClose = TRUE;
  869.     }
  870.  
  871.     if (akCheck(arg->argKind, akbVarNeeded))
  872.     fprintf(file, "%s", arg->argVarName);
  873.     else if (akCheck(arg->argKind, akbSendRcv)) {
  874.     if (akCheck(arg->argKind, akbIndefinite)) {
  875.         fprintf(file, "(In%dP->%s.msgtl_header.msgt_inline) ",
  876.             arg->argRequestPos,
  877.             arg->argTTName);
  878.         fprintf(file, "? %s ", InArgMsgField(arg));
  879.         fprintf(file, ": *((%s **)%s)",
  880.             FetchServerType(arg->argType->itElement),
  881.             InArgMsgField(arg));
  882.     }
  883.     else
  884.         fprintf(file, "%s", InArgMsgField(arg));
  885.     }
  886.     else
  887.     fprintf(file, "OutP->%s", arg->argMsgField);
  888.  
  889.     if (NeedClose)
  890.     fprintf(file, ")");
  891.  
  892.     if (!argByReferenceServer(arg) && (arg->argMultiplier > 1))
  893.     fprintf(file, " / %d", arg->argMultiplier);
  894. }
  895.  
  896. static void
  897. WriteDestroyArg(file, arg)
  898.     FILE *file;
  899.     register argument_t *arg;
  900. {
  901.     register ipc_type_t *it = arg->argType;
  902.  
  903.     if (akCheck(arg->argKind, akbIndefinite)) {
  904.     /*
  905.      * Deallocate only if out-of-line.
  906.      */
  907.     argument_t *count = arg->argCount;
  908.     ipc_type_t *btype = it->itElement;
  909.     int    multiplier = btype->itTypeSize / btype->itNumber;
  910.  
  911.     fprintf(file, "\tif (!In%dP->%s.msgtl_header.msgt_inline)\n",
  912.         arg->argRequestPos, arg->argTTName);
  913.     fprintf(file, "\t\tmig_deallocate(*(char **)%s, ",
  914.         InArgMsgField(arg));
  915.     if (multiplier > 1)
  916.         fprintf(file, "%d * ", multiplier);
  917.     fprintf(file, " %s);\n",
  918.         InArgMsgField(count));
  919.     }
  920.     else {
  921.     if (akCheck(arg->argKind, akbVarNeeded))
  922.         fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName);
  923.     else
  924.         fprintf(file, "\t%s(%s);\n", it->itDestructor,
  925.         InArgMsgField(arg));
  926.     }
  927. }
  928.  
  929. static void
  930. WriteDestroyPortArg(file, arg)
  931.     FILE *file;
  932.     register argument_t *arg;
  933. {
  934.     register ipc_type_t *it = arg->argType;
  935.  
  936.     /*
  937.      *    If a translated port argument occurs in the body of a request
  938.      *    message, and the message is successfully processed, then the
  939.      *    port right should be deallocated.  However, the called function
  940.      *    didn't see the port right; it saw the translation.  So we have
  941.      *    to release the port right for it.
  942.      */
  943.  
  944.     if ((it->itInTrans != strNULL) &&
  945.     (it->itOutName == MACH_MSG_TYPE_PORT_SEND))
  946.     {
  947.     fprintf(file, "\n");
  948.     fprintf(file, "\tif (IP_VALID(%s))\n", InArgMsgField(arg));
  949.     fprintf(file, "\t\tipc_port_release_send(%s);\n", InArgMsgField(arg));
  950.     }
  951. }
  952.  
  953. /*
  954.  * Check whether WriteDestroyPortArg would generate any code for arg.
  955.  */
  956. boolean_t
  957. CheckDestroyPortArg(arg)
  958.     register argument_t *arg;
  959. {
  960.     register ipc_type_t *it = arg->argType;
  961.  
  962.     if ((it->itInTrans != strNULL) &&
  963.     (it->itOutName == MACH_MSG_TYPE_PORT_SEND))
  964.     {
  965.     return TRUE;
  966.     }
  967.     return FALSE;
  968. }
  969.  
  970. static void
  971. WriteServerCall(file, rt)
  972.     FILE *file;
  973.     routine_t *rt;
  974. {
  975.     boolean_t NeedClose = FALSE;
  976.  
  977.     fprintf(file, "\t");
  978.     if (rt->rtServerReturn != argNULL)
  979.     {
  980.     argument_t *arg = rt->rtServerReturn;
  981.     ipc_type_t *it = arg->argType;
  982.  
  983.     fprintf(file, "OutP->%s = ", arg->argMsgField);
  984.     if (it->itOutTrans != strNULL)
  985.     {
  986.         fprintf(file, "%s(", it->itOutTrans);
  987.         NeedClose = TRUE;
  988.     }
  989.     }
  990.     fprintf(file, "%s(", rt->rtServerName);
  991.     WriteList(file, rt->rtArgs, WriteServerCallArg, akbServerArg, ", ", "");
  992.     if (NeedClose)
  993.     fprintf(file, ")");
  994.     fprintf(file, ");\n");
  995. }
  996.  
  997. static void
  998. WriteGetReturnValue(file, rt)
  999.     FILE *file;
  1000.     register routine_t *rt;
  1001. {
  1002.     if (rt->rtServerReturn != rt->rtRetCode)
  1003.     fprintf(file, "\tOutP->%s = KERN_SUCCESS;\n",
  1004.         rt->rtRetCode->argMsgField);
  1005. }
  1006.  
  1007. static void
  1008. WriteCheckReturnValue(file, rt)
  1009.     FILE *file;
  1010.     register routine_t *rt;
  1011. {
  1012.     if (rt->rtServerReturn == rt->rtRetCode)
  1013.     {
  1014.     fprintf(file, "\tif (OutP->%s != KERN_SUCCESS)\n",
  1015.         rt->rtRetCode->argMsgField);
  1016.     fprintf(file, "\t\treturn;\n");
  1017.     }
  1018. }
  1019.  
  1020. static void
  1021. WritePackArgType(file, arg)
  1022.     FILE *file;
  1023.     register argument_t *arg;
  1024. {
  1025.     fprintf(file, "\n");
  1026.  
  1027.     WritePackMsgType(file, arg->argType, arg->argDeallocate, arg->argLongForm,
  1028.              !IsKernelServer, "OutP->%s", "%s", arg->argTTName);
  1029. }
  1030.  
  1031. static void
  1032. WritePackArgValue(file, arg)
  1033.     FILE *file;
  1034.     register argument_t *arg;
  1035. {
  1036.     register ipc_type_t *it = arg->argType;
  1037.  
  1038.     fprintf(file, "\n");
  1039.  
  1040.     if (it->itInLine && it->itVarArray) {
  1041.  
  1042.     if (it->itString) {
  1043.         /*
  1044.          *    Copy variable-size C string with mig_strncpy.
  1045.          *    Save the string length (+ 1 for trailing 0)
  1046.          *    in the argument`s count field.
  1047.          */
  1048.         fprintf(file,
  1049.         "\tOutP->%s = mig_strncpy(OutP->%s, %s, %d);\n",
  1050.         arg->argCount->argMsgField,
  1051.         arg->argMsgField,
  1052.         arg->argVarName,
  1053.         it->itNumber);
  1054.     }
  1055.     else {
  1056.         register argument_t *count = arg->argCount;
  1057.         register ipc_type_t *btype = it->itElement;
  1058.  
  1059.         /* Note btype->itNumber == count->argMultiplier */
  1060.  
  1061.         if (it->itIndefinite) {
  1062.         fprintf(file, "\tif (%s > %d) {\n",
  1063.             count->argVarName,
  1064.             it->itNumber/btype->itNumber);
  1065.         fprintf(file, "\t\tOutP->%s.msgtl_header.msgt_inline = FALSE;\n",
  1066.             arg->argTTName);
  1067.         fprintf(file, "\t\t*((%s *)OutP->%s) = %s;\n",
  1068.             FetchServerType(btype),
  1069.             arg->argMsgField,
  1070.             arg->argVarName);
  1071.         if (!arg->argRoutine->rtSimpleFixedReply)
  1072.             fprintf(file, "\t\tmsgh_simple = FALSE;\n");
  1073.         fprintf(file, "\t}\n\telse {\n\t");
  1074.         }
  1075.         fprintf(file, "\tbcopy((char *) %s, (char *) OutP->%s, ",
  1076.         arg->argVarName, arg->argMsgField);
  1077.         if (btype->itTypeSize > 1)
  1078.         fprintf(file, "%d * ",
  1079.             btype->itTypeSize);
  1080.         fprintf(file, "%s);\n",
  1081.         count->argVarName);
  1082.         if (it->itIndefinite)
  1083.         fprintf(file, "\t}\n");
  1084.     }
  1085.     }
  1086.     else if (arg->argMultiplier > 1)
  1087.     WriteCopyType(file, it, "OutP->%s", "/* %s */ %d * %s",
  1088.               arg->argMsgField,
  1089.               arg->argMultiplier,
  1090.               arg->argVarName);
  1091.     else if (it->itOutTrans != strNULL)
  1092.     WriteCopyType(file, it, "OutP->%s", "/* %s */ %s(%s)",
  1093.               arg->argMsgField, it->itOutTrans, arg->argVarName);
  1094.     else
  1095.     WriteCopyType(file, it, "OutP->%s", "/* %s */ %s",
  1096.               arg->argMsgField, arg->argVarName);
  1097. }
  1098.  
  1099. static void
  1100. WriteCopyArgValue(file, arg)
  1101.     FILE *file;
  1102.     argument_t *arg;
  1103. {
  1104.     fprintf(file, "\n");
  1105.     WriteCopyType(file, arg->argType, "/* %d */ OutP->%s", "In%dP->%s",
  1106.           arg->argRequestPos, arg->argMsgField);
  1107. }
  1108.  
  1109. static void
  1110. WriteAdjustMsgSimple(file, arg)
  1111.     FILE *file;
  1112.     register argument_t *arg;
  1113. {
  1114.     /* akbVarNeeded must be on */
  1115.  
  1116.     if (!arg->argRoutine->rtSimpleFixedReply)
  1117.     {
  1118.     fprintf(file, "\n");
  1119.     fprintf(file, "\tif (MACH_MSG_TYPE_PORT_ANY(%s))\n", arg->argVarName);
  1120.     fprintf(file, "\t\tmsgh_simple = FALSE;\n");
  1121.     }
  1122. }
  1123.  
  1124. static void
  1125. WriteAdjustMsgCircular(file, arg)
  1126.     FILE *file;
  1127.     register argument_t *arg;
  1128. {
  1129.     fprintf(file, "\n");
  1130.  
  1131.     if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
  1132.     fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n",
  1133.         arg->argPoly->argVarName);
  1134.  
  1135.     /*
  1136.      *    The carried port right can be accessed in OutP->XXXX.  Normally
  1137.      *    the server function stuffs it directly there.  If it is InOut,
  1138.      *    then it has already been copied into the reply message.
  1139.      *    If the server function deposited it into a variable (perhaps
  1140.      *    because the reply message is variable-sized) then it has already
  1141.      *    been copied into the reply message.  Note we must use InHeadP
  1142.      *    (or In0P->Head) and OutHeadP to access the message headers,
  1143.      *    because of the variable-sized messages.
  1144.      */
  1145.  
  1146.     fprintf(file, "\tif (IP_VALID((ipc_port_t) InHeadP->msgh_reply_port) &&\n");
  1147.     fprintf(file, "\t    IP_VALID((ipc_port_t) OutP->%s) &&\n", arg->argMsgField);
  1148.     fprintf(file, "\t    ipc_port_check_circularity((ipc_port_t) OutP->%s, (ipc_port_t) InHeadP->msgh_reply_port))\n", arg->argMsgField);
  1149.     fprintf(file, "\t\tOutHeadP->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n");
  1150. }
  1151.  
  1152. /*
  1153.  * Calculate the size of a variable-length message field.
  1154.  */
  1155. static void
  1156. WriteArgSize(file, arg)
  1157.     FILE *file;
  1158.     register argument_t *arg;
  1159. {
  1160.     register ipc_type_t *ptype = arg->argType;
  1161.     register int bsize = ptype->itElement->itTypeSize;
  1162.     register argument_t *count = arg->argCount;
  1163.  
  1164.     if (ptype->itIndefinite) {
  1165.     /*
  1166.      * Check descriptor.  If out-of-line, use standard size.
  1167.      */
  1168.     fprintf(file, "(OutP->%s.msgtl_header.msgt_inline) ? ",
  1169.         arg->argTTName);
  1170.     }
  1171.  
  1172.     if (bsize > 1)
  1173.     fprintf(file, "%d * ", bsize);
  1174.     if (ptype->itString)
  1175.     /* get count from descriptor in message */
  1176.     fprintf(file, "OutP->%s", count->argMsgField);
  1177.     else
  1178.     /* get count from argument */
  1179.     fprintf(file, "%s", count->argVarName);
  1180.  
  1181.     /*
  1182.      * If the base type size is not a multiple of sizeof(int) [4],
  1183.      * we have to round up.
  1184.      */
  1185.     if (bsize % 4 != 0)
  1186.     fprintf(file, " + 3 & ~3");
  1187.  
  1188.     if (ptype->itIndefinite) {
  1189.     fprintf(file, " : sizeof(%s *)",
  1190.         FetchServerType(ptype->itElement));
  1191.     }
  1192. }
  1193.  
  1194. /*
  1195.  * Adjust message size and advance reply pointer.
  1196.  * Called after packing a variable-length argument that
  1197.  * has more arguments following.
  1198.  */
  1199. static void
  1200. WriteAdjustMsgSize(file, arg)
  1201.     FILE *file;
  1202.     register argument_t *arg;
  1203. {
  1204.     register routine_t *rt = arg->argRoutine;
  1205.     register ipc_type_t *ptype = arg->argType;
  1206.  
  1207.     /* There are more Out arguments.  We need to adjust msgh_size
  1208.        and advance OutP, so we save the size of the current field
  1209.        in msgh_size_delta. */
  1210.  
  1211.     fprintf(file, "\tmsgh_size_delta = ");
  1212.     WriteArgSize(file, arg);
  1213.     fprintf(file, ";\n");
  1214.  
  1215.     if (rt->rtNumReplyVar == 1)
  1216.     /* We can still address the message header directly.  Fill
  1217.        in the size field. */
  1218.  
  1219.     fprintf(file, "\tOutP->Head.msgh_size = %d + msgh_size_delta;\n",
  1220.             rt->rtReplySize);
  1221.     else
  1222.     if (arg->argReplyPos == 0)
  1223.     /* First variable-length argument.  The previous msgh_size value
  1224.        is the minimum reply size. */
  1225.  
  1226.     fprintf(file, "\tmsgh_size = %d + msgh_size_delta;\n",
  1227.         rt->rtReplySize);
  1228.     else
  1229.     fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
  1230.  
  1231.     fprintf(file,
  1232.     "\tOutP = (Reply *) ((char *) OutP + msgh_size_delta - %d);\n",
  1233.     ptype->itTypeSize + ptype->itPadSize);
  1234. }
  1235.  
  1236. /*
  1237.  * Calculate the size of the message.  Called after the
  1238.  * last argument has been packed.
  1239.  */
  1240. static void
  1241. WriteFinishMsgSize(file, arg)
  1242.     FILE *file;
  1243.     register argument_t *arg;
  1244. {
  1245.     /* No more Out arguments.  If this is the only variable Out
  1246.        argument, we can assign to msgh_size directly. */
  1247.  
  1248.     if (arg->argReplyPos == 0) {
  1249.     fprintf(file, "\tOutP->Head.msgh_size = %d + (",
  1250.             arg->argRoutine->rtReplySize);
  1251.     WriteArgSize(file, arg);
  1252.     fprintf(file, ");\n");
  1253.     }
  1254.     else {
  1255.     fprintf(file, "\tmsgh_size += ");
  1256.     WriteArgSize(file, arg);
  1257.     fprintf(file, ";\n");
  1258.     }
  1259. }
  1260.  
  1261. static void
  1262. WritePackArg(file, arg)
  1263.     FILE *file;
  1264.     argument_t *arg;
  1265. {
  1266.     if (akCheck(arg->argKind, akbReplyInit))
  1267.     WritePackArgType(file, arg);
  1268.  
  1269.     if ((akIdent(arg->argKind) == akePoly) &&
  1270.     akCheck(arg->argKind, akbReturnSnd))
  1271.     WriteAdjustMsgSimple(file, arg);
  1272.  
  1273.     if (akCheckAll(arg->argKind, akbReturnSnd|akbVarNeeded))
  1274.     WritePackArgValue(file, arg);
  1275.     else if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable))
  1276.     {
  1277.     register ipc_type_t *it = arg->argType;
  1278.     register argument_t *count = arg->argCount;
  1279.  
  1280.     if (it->itString)
  1281.     {
  1282.         /* Need to call strlen to calculate the size of the argument. */
  1283.         fprintf(file, "\tOutP->%s = strlen(OutP->%s) + 1;\n",
  1284.             count->argMsgField,
  1285.             arg->argMsgField);
  1286.     }
  1287.     else if (it->itIndefinite)
  1288.     {
  1289.         fprintf(file, "\tif (%s > %d) {\n",
  1290.             count->argVarName,
  1291.             it->itNumber/it->itElement->itNumber);
  1292.         fprintf(file, "\t\tOutP->%s.msgtl_header.msgt_inline = FALSE;\n",
  1293.             arg->argTTName);
  1294.         if (!arg->argRoutine->rtSimpleFixedReply)
  1295.         fprintf(file, "\t\tmsgh_simple = FALSE;\n");
  1296.         fprintf(file, "\t}\n");
  1297.     }
  1298.     }
  1299.  
  1300.     if (akCheck(arg->argKind, akbReplyCopy))
  1301.     WriteCopyArgValue(file, arg);
  1302.  
  1303.     /*
  1304.      *    If this is a KernelServer, and the reply message contains
  1305.      *    a receive right, we must check for the possibility of a
  1306.      *    port/message circularity.  If queueing the reply message
  1307.      *    would cause a circularity, we mark the reply message
  1308.      *    with the circular bit.
  1309.      */
  1310.  
  1311.     if (IsKernelServer &&
  1312.     akCheck(arg->argKind, akbReturnSnd) &&
  1313.     ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) ||
  1314.      (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)))
  1315.     WriteAdjustMsgCircular(file, arg);
  1316.  
  1317. }
  1318.  
  1319. /*
  1320.  * Handle reply arguments - fill in message types and copy arguments
  1321.  * that need to be copied.
  1322.  */
  1323. WritePackReplyArgs(file, rt)
  1324.     FILE *file;
  1325.     register routine_t *rt;
  1326. {
  1327.     register argument_t *arg;
  1328.     register argument_t *lastVarArg;
  1329.  
  1330.     lastVarArg = argNULL;
  1331.     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
  1332.  
  1333.     /*
  1334.      * Adjust message size and advance message pointer if
  1335.      * the last reply argument was variable-length and the
  1336.      * request position will change.
  1337.      */
  1338.     if (lastVarArg != argNULL &&
  1339.         lastVarArg->argReplyPos < arg->argReplyPos)
  1340.     {
  1341.         WriteAdjustMsgSize(file, lastVarArg);
  1342.         lastVarArg = argNULL;
  1343.     }
  1344.  
  1345.     /*
  1346.      * Copy the argument
  1347.      */
  1348.     WritePackArg(file, arg);
  1349.  
  1350.     /*
  1351.      * Remember whether this was variable-length.
  1352.      */
  1353.     if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable))
  1354.         lastVarArg = arg;
  1355.     }
  1356.  
  1357.     /*
  1358.      * Finish the message size.
  1359.      */
  1360.     if (lastVarArg != argNULL)
  1361.     WriteFinishMsgSize(file, lastVarArg);
  1362. }
  1363.  
  1364. static void
  1365. WriteFieldDecl(file, arg)
  1366.     FILE *file;
  1367.     argument_t *arg;
  1368. {
  1369.     WriteFieldDeclPrim(file, arg, FetchServerType);
  1370. }
  1371.  
  1372. static void
  1373. WriteRoutine(file, rt)
  1374.     FILE *file;
  1375.     register routine_t *rt;
  1376. {
  1377.     fprintf(file, "\n");
  1378.  
  1379.     fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
  1380.     fprintf(file, "mig_internal novalue _X%s\n", rt->rtName);
  1381.     fprintf(file, "#if\t%s\n", NewCDecl);
  1382.     fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
  1383.     fprintf(file, "#else\n");
  1384.     fprintf(file, "\t(InHeadP, OutHeadP)\n");
  1385.     fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
  1386.     fprintf(file, "#endif\n");
  1387.  
  1388.     fprintf(file, "{\n");
  1389.     WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request");
  1390.     WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply");
  1391.  
  1392.     WriteVarDecls(file, rt);
  1393.  
  1394.     WriteList(file, rt->rtArgs, WriteCheckDecl, akbRequestQC, "\n", "\n");
  1395.     /* 
  1396.      * The casts in the "?:" expression are necessary to keep the MIPS
  1397.      * compiler from complaining "operands of : have incompatible types".
  1398.      * MDK 30-Oct-1991.
  1399.      */
  1400.     WriteList(file, rt->rtArgs,
  1401.           (IsKernelServer ? (void (*)())WriteTypeDeclOut 
  1402.                          : (void (*)())WriteTypeDeclIn),
  1403.           akbReplyInit, "\n", "\n");
  1404.  
  1405.     WriteList(file, rt->rtArgs, WriteLocalVarDecl,
  1406.           akbVarNeeded, ";\n", ";\n\n");
  1407.  
  1408.     WriteCheckHead(file, rt);
  1409.  
  1410.     WriteTypeCheckRequestArgs(file, rt);
  1411.     WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", "");
  1412.  
  1413.     WriteServerCall(file, rt);
  1414.     WriteGetReturnValue(file, rt);
  1415.  
  1416.     WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", "");
  1417.  
  1418.     /*
  1419.      * For one-way routines, it doesn`t make sense to check the return
  1420.      * code, because we return immediately afterwards.  However,
  1421.      * kernel servers may want to deallocate port arguments - and the
  1422.      * deallocation must not be done if the return code is not KERN_SUCCESS.
  1423.      */
  1424.     if (rt->rtOneWay || rt->rtNoReplyArgs)
  1425.     {
  1426.     if (IsKernelServer)
  1427.     {
  1428.         if (rtCheckMaskFunction(rt->rtArgs, akbSendBody|akbSendRcv,
  1429.                 CheckDestroyPortArg))
  1430.         {
  1431.         WriteCheckReturnValue(file, rt);
  1432.         }
  1433.         WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg,
  1434.              akbSendBody|akbSendRcv, "", "");
  1435.     }
  1436.     }
  1437.     else
  1438.     {
  1439.     WriteCheckReturnValue(file, rt);
  1440.  
  1441.     if (IsKernelServer)
  1442.         WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg,
  1443.              akbSendBody|akbSendRcv, "", "");
  1444.  
  1445.     WriteReplyInit(file, rt);
  1446.     WritePackReplyArgs(file, rt);
  1447.     WriteReplyHead(file, rt);
  1448.     }
  1449.  
  1450.     fprintf(file, "}\n");
  1451. }
  1452.  
  1453. static void
  1454. WriteStubArgDecl(file, arg)
  1455.     FILE *file;
  1456.     argument_t *arg;
  1457. {
  1458.     char *ref = argByReferenceServer(arg) ? "*" : "";
  1459.  
  1460.     fprintf(file, "\t%s %s%s", arg->argType->itServerType,
  1461.         ref, arg->argVarName);
  1462. }
  1463.  
  1464. static void
  1465. WriteStubDecl(file, rt)
  1466.     FILE *file;
  1467.     register routine_t *rt;
  1468. {
  1469.     fprintf(file, "\n");
  1470.     fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
  1471.     fprintf(file, "%s %s\n", ServerSideType(rt), rt->rtServerName);
  1472.     fprintf(file, "#if\t%s\n", NewCDecl);
  1473.     fprintf(file, "(\n");
  1474.     WriteList(file, rt->rtArgs, WriteStubArgDecl,
  1475.           akbServerArg, ",\n", "\n");
  1476.     fprintf(file, ")\n");
  1477.     fprintf(file, "#else\n");
  1478.     fprintf(file, "\t(");
  1479.     WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", ", "");
  1480.     fprintf(file, ")\n");
  1481.     WriteList(file, rt->rtArgs, WriteStubArgDecl,
  1482.           akbServerArg, ";\n", ";\n");
  1483.     fprintf(file, "#endif\n");
  1484.     fprintf(file, "{\n");
  1485. }
  1486.  
  1487. void
  1488. WriteServer(file, stats)
  1489.     FILE *file;
  1490.     statement_t *stats;
  1491. {
  1492.     register statement_t *stat;
  1493.  
  1494.     WriteProlog(file);
  1495.     for (stat = stats; stat != stNULL; stat = stat->stNext)
  1496.     switch (stat->stKind)
  1497.     {
  1498.       case skRoutine:
  1499.         WriteRoutine(file, stat->stRoutine);
  1500.         break;
  1501.       case skImport:
  1502.       case skSImport:
  1503.         WriteImport(file, stat->stFileName);
  1504.         break;
  1505.       case skUImport:
  1506.         break;
  1507.       default:
  1508.         fatal("WriteServer(): bad statement_kind_t (%d)",
  1509.           (int) stat->stKind);
  1510.     }
  1511.     WriteEpilog(file, stats);
  1512. }
  1513. @
  1514.  
  1515.  
  1516. 1.1
  1517. log
  1518. @Initial revision
  1519. @
  1520. text
  1521. @d29 3
  1522. d1367 5
  1523. d1373 2
  1524. a1374 1
  1525.           IsKernelServer ? WriteTypeDeclOut : WriteTypeDeclIn,
  1526. @
  1527.